import axios from 'axios';
import { INestApplication } from '@nestjs/common';
import { OpenAPIObject, SwaggerModule } from '@nestjs/swagger';

/**
 * 排除 getaway 的接口
 * @param document swagger 文档对象
 * @param moduleName 排除前缀
 */
export function excludeModulePaths(
  document: OpenAPIObject,
  moduleName: string,
) {
  for (const path in document.paths) {
    if (path.startsWith(`/${moduleName.toLowerCase()}`)) {
      delete document.paths[path];
    }
  }
}

/**
 * 聚合最终的网关API文档 并挂载
 * @param app 挂载主体app
 * @param gatewayDoc 传入的文档
 */
export async function aggregateSwaggerDocuments(
  app: INestApplication,
  gatewayDoc: OpenAPIObject,
) {
  const services = [
    {
      name: 'common',
      url: 'http://localhost:5101/swagger-docs-json',
    },
    {
      name: 'user',
      url: 'http://localhost:5102/swagger-docs-json',
    },
    // 添加更多微服务
  ];
  for (const service of services) {
    try {
      // TODO
      // 查询服务是否注册
      if (
        service.name === 'user' ||
        service.name === 'news' ||
        service.name === 'common'
      ) {
        const response = await axios.get<OpenAPIObject>(service.url);
        const serviceDoc = response.data;
        // 合并 paths，添加微服务前缀避免冲突
        gatewayDoc.paths = {
          ...gatewayDoc.paths,
          ...addPrefixToPaths(serviceDoc.paths),
        };

        // 合并 components 中的 schemas，添加前缀避免冲突
        gatewayDoc.components = gatewayDoc.components || {};
        gatewayDoc.components.schemas = {
          ...gatewayDoc.components.schemas,
          ...addPrefixToSchemas(serviceDoc.components?.schemas),
        };

        // 合并其他 components，如 responses、parameters，添加前缀避免冲突
        gatewayDoc.components.responses = {
          ...gatewayDoc.components.responses,
          ...addPrefixToComponents(serviceDoc.components?.responses),
        };
        gatewayDoc.components.parameters = {
          ...gatewayDoc.components.parameters,
          ...addPrefixToComponents(serviceDoc.components?.parameters),
        };
        // gatewayDoc.servers = [{ url: service.serverUrl }];
        // console.log(serviceDoc, 'document');
        // console.log(gatewayDoc, 'document');
      }
    } catch (error) {
      console.error(
        `Failed to load Swagger document for ${service.name}`,
        error,
      );
    }
  }

  // console.log(gatewayDoc, 'document');
  // 更新服务的 servers 信息
  for (const path in gatewayDoc.paths) {
    if (path.startsWith('/common')) {
      gatewayDoc.paths[path].servers = [{ url: 'http://localhost:5101' }];
    }
    if (path.startsWith('/user')) {
      gatewayDoc.paths[path].servers = [{ url: 'http://localhost:5102' }];
    }
  }
  // 将聚合后的文档设置在 '/api-docs' 路径
  SwaggerModule.setup('swagger-docs', app, gatewayDoc);
}

/**
 * 合并 paths，添加微服务前缀避免冲突
 * @param paths 待处理的paths
 * @returns 处理后的paths
 */
function addPrefixToPaths(paths: any): any {
  const newPaths = {};
  for (const path in paths) {
    if (paths.hasOwnProperty(path)) {
      newPaths[`${path}`] = paths[path];
    }
  }
  return newPaths;
}

/**
 * 合并 components 中的 schemas，添加前缀避免冲突
 * @param schemas 待处理的schemas
 * @returns 处理后的schemas
 */
function addPrefixToSchemas(schemas: any): any {
  const newSchemas = {};
  for (const schema in schemas) {
    if (schemas.hasOwnProperty(schema)) {
      newSchemas[`${schema}`] = schemas[schema];
    }
  }
  return newSchemas;
}

/**
 * 合并其他 components，如 responses、parameters，添加前缀避免冲突
 * @param components 待处理的responses、parameters
 * @returns 处理后的 responses、parameters
 */
function addPrefixToComponents(components: any): any {
  const newComponents = {};
  for (const component in components) {
    if (components.hasOwnProperty(component)) {
      newComponents[`${component}`] = components[component];
    }
  }
  return newComponents;
}
